package pl.streamsoft.test.model;

import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import pl.streamsoft.test.model.entities.CurrencyAverageEntity;
import pl.streamsoft.test.model.entities.CurrencyEntity;
import pl.streamsoft.test.model.entities.CurrencyTypeEntity;
import pl.streamsoft.test.model.entities.DateEntryEntity;
import pl.streamsoft.test.model.exceptions.DAOException;

public class CurrenciesHibernate implements CurrenciesDAO {

	private Configuration configuration;
	private ServiceRegistry serviceRegistry;
	private static SessionFactory sessionFactory;
	private Session session;

	public CurrenciesHibernate() {
		if (sessionFactory == null) {
			System.out.println("Initializing Session factory");
			configuration = new Configuration();
			configuration.configure();

			serviceRegistry = new ServiceRegistryBuilder().applySettings(
					configuration.getProperties()).buildServiceRegistry();
			sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		}
	}

	public void beginTransaction() throws DAOException {
		session = sessionFactory.openSession();
		session.beginTransaction();
		if (session == null) {
			throw new DAOException("Session creating failed");
		}

	}

	public void commitTransaction() throws DAOException {
		session.getTransaction().commit();
		session.flush();
		session.close();
	}

	public void rollbackTransaction() throws DAOException {
		session.getTransaction().rollback();
		session.flush();
		session.close();
	}

	public CurrencyEntity insert(CurrencyEntity entity) throws DAOException {
		if (entity.getType() == null)
			throw new DAOException("Inserting failed. No currency type defined");
		if (entity.getDate() == null)
			throw new DAOException("Inserting failed. No date defined");

		session.persist(entity);
		return entity;
	}

	public CurrencyEntity update(CurrencyEntity entity) throws DAOException {
		session.merge(entity);
		return entity;
	}

	public CurrencyEntity delete(CurrencyEntity entity) throws DAOException {
		session.delete(entity);
		return entity;
	}

	public CurrencyEntity findCurrency(Integer id) throws DAOException {
		return (CurrencyEntity) session.get(CurrencyEntity.class, id);
	}

	public List<CurrencyEntity> findAllCurrencies(CurrencyTypeEntity typeEntity)
			throws DAOException {
		Query query = session.getNamedQuery("findAllCurrenciesByType");
		query.setParameter("type", typeEntity);

		List<CurrencyEntity> list = query.list();
		return list;
	}

	public List<CurrencyEntity> findAllCurrencies(
			CurrencyTypeEntity typeEntity, int limit, int offset)
			throws DAOException {
		Query query = session.getNamedQuery("findAllCurrenciesByTypeLimited");
		query.setParameter("currencyType", typeEntity);
		query.setMaxResults(limit);
		query.setFirstResult(offset);

		List<CurrencyEntity> list = query.list();
		return list;
	}

	public List<CurrencyEntity> findCurrenciesByDate(Date from, Date to)
			throws DAOException {
		Query query = session.getNamedQuery("findAllCurrenciesByDate");
		query.setParameter("from", from);
		query.setParameter("to", to);

		List<CurrencyEntity> list = query.list();
		return list;
	}

	public List<CurrencyEntity> findCurrenciesByDateAndType(Date from, Date to,
			CurrencyTypeEntity typeEntity) throws DAOException {
		Query query = session.getNamedQuery("findAllCurrenciesByDateAndType");
		query.setParameter("type", typeEntity);
		query.setParameter("from", from);
		query.setParameter("to", to);

		List<CurrencyEntity> list = query.list();
		return list;
	}

	public CurrencyTypeEntity insert(CurrencyTypeEntity entity)
			throws DAOException {
		session.persist(entity);
		return entity;
	}

	public CurrencyTypeEntity update(CurrencyTypeEntity entity)
			throws DAOException {
		session.merge(entity);
		return entity;
	}

	public CurrencyTypeEntity delete(CurrencyTypeEntity entity)
			throws DAOException {
		session.delete(entity);
		return entity;
	}

	public CurrencyTypeEntity findCurrencyType(int id) throws DAOException {
		CurrencyTypeEntity currencyType = (CurrencyTypeEntity) session.get(
				CurrencyEntity.class, id);
		if (currencyType == null) {
			throw new DAOException("Currency type not found");
		}
		return currencyType;
	}

	public CurrencyTypeEntity findCurrencyType(String acronym)
			throws DAOException {
		Query query = session.getNamedQuery("findAllCurrencyTypesByAcronym");
		query.setParameter("acronym", acronym);

		CurrencyTypeEntity currencyType = (CurrencyTypeEntity) query
				.uniqueResult();
		if (currencyType == null) {
			throw new DAOException("Currency type not found");
		}
		return currencyType;
	}

	public List<CurrencyTypeEntity> findAllCurrencyTypes() throws DAOException {
		Query query = session.getNamedQuery("findAllCurrencyTypes");
		return (List<CurrencyTypeEntity>) query.list();
	}

	public DateEntryEntity insert(DateEntryEntity entity) throws DAOException {
		session.persist(entity);
		return entity;
	}

	public DateEntryEntity update(DateEntryEntity entity) throws DAOException {
		session.merge(entity);
		return entity;
	}

	public DateEntryEntity delete(DateEntryEntity entity) throws DAOException {
		session.delete(entity);
		return entity;
	}

	public DateEntryEntity findDateEntry(int id) throws DAOException {
		DateEntryEntity dateEntry = (DateEntryEntity) session.get(
				CurrencyEntity.class, id);
		if (dateEntry == null) {
			throw new DAOException("Date not found");
		}
		return dateEntry;
	}

	public DateEntryEntity findDateEntry(Date date) throws DAOException {
		Query query = session.getNamedQuery("findDateEntryByDate");
		query.setCacheable(true);
		query.setParameter("date", date);
		DateEntryEntity dateEntry = (DateEntryEntity) query.uniqueResult();
		if (dateEntry == null) {
			throw new DAOException("Date not found");
		}
		return dateEntry;
	}

	public List<DateEntryEntity> findAllDateEntries() throws DAOException {
		// TODO Auto-generated method stub
		return null;
	}

	public CurrencyAverageEntity insert(CurrencyAverageEntity entity)
			throws DAOException {
		session.persist(entity);
		return entity;
	}

	public CurrencyAverageEntity update(CurrencyAverageEntity entity)
			throws DAOException {
		session.merge(entity);
		return entity;
	}

	public CurrencyAverageEntity delete(CurrencyAverageEntity entity)
			throws DAOException {
		session.delete(entity);
		return entity;
	}

	public CurrencyAverageEntity findCurrencyAverage(int id)
			throws DAOException {
		return (CurrencyAverageEntity) session.get(CurrencyAverageEntity.class,
				id);
	}

	public CurrencyAverageEntity findCurrencyAverage(
			CurrencyTypeEntity currencyTypeEntity) throws DAOException {
		Query query = session.getNamedQuery("findCurrencyAverage");
		query.setParameter("type", currencyTypeEntity);
		CurrencyAverageEntity currencyAverage = (CurrencyAverageEntity) query
				.uniqueResult();
		if (currencyAverage == null) {
			throw new DAOException("CurrencyAverageEntity not found.");
		}

		return currencyAverage;
	}

}
